# - Find Thrift (a cross platform RPC lib/tool)
# This module defines
#  THRIFT_VERSION_STRING, version string of ant if found
#  THRIFT_LIBRARIES, static or shared libraries to link
#  THRIFT_INCLUDE_DIR, where to find THRIFT headers
#  THRIFT_COMPILER, thrift compiler executable
#  THRIFT_FOUND, If false, do not try to use ant
#
# Imported target:
#  thrift ,shared thrift library
#  thrift_static,same with target 'thrift' if target 'thrift' is static for not MSVC
#  thrift_static_md,same with target 'thrift' if target 'thrift' is static with /MD for MSVC
#  thrift_static_mt,same with target 'thrift' if target 'thrift' is static with /MT for MSVC
#
# Function:
#  thrift_gen_cpp(<path to thrift file> <output variable with file list>)
# 
# Initial work was done by Cloudera https://github.com/cloudera/Impala
# 2014 - modified by snikulov
# 2018 - modified by guyadong

# FindBoost.cmake supported imported targets after cmake version 3.5
cmake_minimum_required( VERSION 3.5 )

# prefer the thrift version supplied in THRIFT_HOME (cmake -DTHRIFT_HOME then environment)
find_path(THRIFT_INCLUDE_DIR
    NAMES
        thrift/Thrift.h
    HINTS
        ${THRIFT_HOME}
        ENV THRIFT_HOME
        /usr/local
        /opt/local
    PATH_SUFFIXES
        include
)
option(USE_THRIFT_WITH_BOOSTTHREADS "specify whether the thrift library build with 'WITH_BOOSTTHREADS' option" ON)

macro(FIND_THRIFT_LIBRARY var)
	# prefer the thrift version supplied in THRIFT_HOME
	find_library(${var}
	    NAMES
	        ${ARGN}
	    HINTS
	        ${THRIFT_HOME}
	        ENV THRIFT_HOME
	        /usr/local
	        /opt/local
	    PATH_SUFFIXES
	        lib lib64
	)
endmacro(FIND_THRIFT_LIBRARY)

# 查找thrift依赖库 boost
# 如果相关依赖库找不到则报错退出
macro(FIND_THRIFT_DEPENDENCIES)
	# 依赖的库
	set(THRIFT_DEPENDENT_LIBRARIES)
	# 依赖库的include文件夹
	set(THRIFT_DEPENDENT_DIRS)

	if(USE_THRIFT_WITH_BOOSTTHREADS)
		find_package(Boost REQUIRED COMPONENTS system thread)
		foreach(_component system thread)
			# boost imported target
			list(APPEND THRIFT_DEPENDENT_LIBRARIES Boost::${_component})
		endforeach()
		# 依赖库的include文件夹
		set(THRIFT_DEPENDENT_DIRS ${Boost_INCLUDE_DIRS})
	endif()
endmacro(FIND_THRIFT_DEPENDENCIES)

# prefer default thrift library
FIND_THRIFT_LIBRARY(THRIFT_LIBRARIES thrift thriftd thriftmd thriftmdd thriftmt thriftmtd)

find_program(THRIFT_COMPILER
    NAMES
        thrift
    HINTS
        ${THRIFT_HOME}
        ENV THRIFT_HOME
        /usr/local
        /opt/local
    PATH_SUFFIXES
        bin bin64
)

if (THRIFT_COMPILER)
    exec_program(${THRIFT_COMPILER}
        ARGS -version OUTPUT_VARIABLE __thrift_OUT RETURN_VALUE THRIFT_RETURN)
    string(REGEX MATCH "[0-9]+.[0-9]+.[0-9]+-[a-z]+$" THRIFT_VERSION_STRING ${__thrift_OUT})

    # define utility function to generate cpp files
    function(thrift_gen_cpp thrift_file THRIFT_CPP_FILES_LIST THRIFT_GEN_INCLUDE_DIR)
        set(_res)
        set(_res_inc_path)
        if(EXISTS ${thrift_file})
            get_filename_component(_target_dir ${thrift_file} NAME_WE)
            message("thrif_gen_cpp: ${thrift_file}")

            if(NOT EXISTS ${CMAKE_BINARY_DIR}/${_target_dir})
                file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/${_target_dir})
            endif()
            exec_program(${THRIFT_COMPILER}
                ARGS -o "${CMAKE_BINARY_DIR}/${_target_dir}" --gen cpp ${thrift_file}
                OUTPUT_VARIABLE __thrift_OUT
                RETURN_VALUE THRIFT_RETURN)
            file(GLOB_RECURSE __result_src "${CMAKE_BINARY_DIR}/${_target_dir}/*.cpp")
            file(GLOB_RECURSE __result_hdr "${CMAKE_BINARY_DIR}/${_target_dir}/*.h")
            list(APPEND _res ${__result_src})
            list(APPEND _res ${__result_hdr})
            if(__result_hdr)
                list(GET __result_hdr 0 _res_inc_path)
                get_filename_component(_res_inc_path ${_res_inc_path} DIRECTORY)
            endif()
        else()
            message("thrift_gen_cpp: file ${thrift_file} does not exists")
        endif()
        set(${THRIFT_CPP_FILES_LIST} "${_res}" PARENT_SCOPE)
        set(${THRIFT_GEN_INCLUDE_DIR} "${_res_inc_path}" PARENT_SCOPE)
    endfunction()
endif ()


include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(THRIFT DEFAULT_MSG THRIFT_INCLUDE_DIR THRIFT_LIBRARIES THRIFT_COMPILER)
mark_as_advanced(THRIFT_LIBRARIES THRIFT_INCLUDE_DIR THRIFT_COMPILER THRIFT_VERSION_STRING)

############################
function(set_thrift_imported_target target build_type imported_location)
	if(NOT TARGET ${target})
		message(FATAL_ERROR "${target} is invalid target")
	endif()
	if(NOT EXISTS ${imported_location})
		message(FATAL_ERROR "${imported_location} is invalid library")
	endif()
	set(_build_type_suffix)
	get_target_property(_type ${target} TYPE)
	if(build_type)
		set(_build_type_suffix _${build_type})
		string(TOUPPER "${_build_type_suffix}" _build_type_suffix)
	endif()
	set_property(TARGET ${target} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${build_type})
	set_target_properties(${target} PROPERTIES
		IMPORTED_LINK_INTERFACE_LANGUAGES${_build_type_suffix} "CXX"
		INTERFACE_INCLUDE_DIRECTORIES "${THRIFT_INCLUDE_DIR};${THRIFT_DEPENDENT_DIRS}"
		IMPORTED_LINK_INTERFACE_LIBRARIES "${THRIFT_DEPENDENT_LIBRARIES};$<$<STREQUAL:${CMAKE_CXX_PLATFORM_ID},MinGW>:-lws2_32>"
		IMPORTED_LOCATION${_build_type_suffix} "${imported_location}"
	)
endfunction(set_thrift_imported_target)

macro(create_thrift_static_target static_postfix)
	set(_var_suffix )
	set(_taget_suffix )
	string(TOUPPER "${static_postfix}" _var_suffix )
	string(TOLOWER "${static_postfix}" _taget_suffix )
	if(_var_suffix)
		set(_var_suffix _${_var_suffix})
		set(_taget_suffix _${_taget_suffix})
	endif()
	set(_taget thrift_static${_taget_suffix})
	FIND_THRIFT_LIBRARY(THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE ${CMAKE_STATIC_LIBRARY_PREFIX}thrift${static_postfix}${CMAKE_STATIC_LIBRARY_SUFFIX})
	FIND_THRIFT_LIBRARY(THRIFT_STATIC_LIBRARY${_var_suffix}_DEBUG ${CMAKE_STATIC_LIBRARY_PREFIX}thrift${static_postfix}d${CMAKE_STATIC_LIBRARY_SUFFIX})
	if(THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE OR THRIFT_STATIC_LIBRARY${_var_suffix}_DEBUG)
		add_library(${_taget} STATIC IMPORTED)
		message("-- IMPORTED STATIC library:${_taget}")
		IF(THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE)
			set_thrift_imported_target(${_taget} "" ${THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE})
			set_thrift_imported_target(${_taget} RELEASE ${THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE})
			set(THRIFT_STATIC_LIBRARY${_var_suffix} ${THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE})
			#message("-- THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE=${THRIFT_STATIC_LIBRARY${_var_suffix}_RELEASE}")
		endif()
		IF(THRIFT_STATIC_LIBRARY${_var_suffix}_DEBUG)
			set_thrift_imported_target(${_taget} DEBUG ${THRIFT_STATIC_LIBRARY${_var_suffix}_DEBUG})
			#message("-- THRIFT_STATIC_LIBRARY${_var_suffix}_DEBUG=${THRIFT_STATIC_LIBRARY${_var_suffix}_DEBUG}")
		endif()
	endif()
	unset(_var_suffix)
endmacro(create_thrift_static_target)

if(THRIFT_FOUND)
	set(Thrift_FOUND TRUE)
	FIND_THRIFT_DEPENDENCIES()

	FIND_THRIFT_LIBRARY(THRIFT_SHARED_LIBRARY ${CMAKE_SHARED_LIBRARY_PREFIX}thrift${CMAKE_SHARED_LIBRARY_SUFFIX})
	if(THRIFT_SHARED_LIBRARY)
		add_library(thrift SHARED IMPORTED)
		message("-- IMPORTED SHARED library:thrift")
		set_thrift_imported_target(thrift RELEASE ${THRIFT_SHARED_LIBRARY})
	endif(THRIFT_SHARED_LIBRARY)

	if(MSVC)
		create_thrift_static_target(md)
		create_thrift_static_target(mt)
	else()
		create_thrift_static_target("")
	endif(MSVC)
elseif(Thrift_FIND_REQUIRED)
	message(FATAL_ERROR "Thrift NOT FOUND")
endif()

unset (THRIFT_DEPENDENT_DIRS)
unset(THRIFT_DEPENDENT_LIBRARIES)